#include "PriorityControlAdmissionControl.h"

Define_Module(PriorityControlAdmissionControl)

void PriorityControlAdmissionControl::initialize()
{
	AbstractAdmissionControl::initialize();

	timeWindow = par("timeWindow");
	switchAverage = par("switchAverage");
	controlDelay = par("controlDelay");
	minPrior = par("minPrior");
	curPrior = minPrior;
	capacity.clear();
	times.clear();
	lastTime = 0.0;
	average = 0.0;
	WATCH(curPrior);
	WATCH(average);
}

bool PriorityControlAdmissionControl::acceptPacket(NetPacket* packet)
{
	process(packet->getArrivalTime().dbl(), (double)(packet->getByteLength()), packet->getPriority());
	return packet->getPriority() >= curPrior;
}

void PriorityControlAdmissionControl::process(double time, double cap, int prior){
	if(lastTime + controlDelay <= time){

		// usuniecie czasow spoza okna
		double minTime = time - timeWindow;
		while(times.size() > 0 && times.front() < minTime)
		{
			times.pop_front();
			capacity.pop_front();
		}

		// obliczenie sredniej przepustowosci
		double sum = 0;
		for(std::list<double>::iterator element = capacity.begin(); element != capacity.end();++element)
			sum += *element;
		sum /= timeWindow;

		average = sum;

		// sterowanie piorytetem
		if(sum > switchAverage)
			curPrior++;
		else if(curPrior > minPrior)
			curPrior--;

		lastTime = time;
	}

	// dodanie badz nie do danych
	if(prior >= curPrior){
		times.push_back(time);
		capacity.push_back(cap);
	}
}
